// 建造者模式

package builder

// 定义单个饭菜的接口
type item interface {
	GetName() string
	GetPrice() float64
}

// 定义汉堡
type burger struct {
	price float64
	name  string
}

func (b *burger) GetName() string {
	return b.name
}

func (b *burger) GetPrice() float64 {
	return b.price
}

// 定义饮料
type drink struct {
	price float64
	name  string
}

func (d *drink) GetName() string {
	return d.name
}

func (d *drink) GetPrice() float64 {
	return d.price
}

// 定义一顿饭的接口
type Meal struct {
	items []item
}

// 添加饭菜
func (m *Meal) addItem(item item) {
	m.items = append(m.items, item)
}

// 对外暴露获得价格的接口
func (m *Meal) GetCost() float64 {
	var cost float64
	for _, item := range m.items {
		cost += item.GetPrice()
	}
	return cost
}

// 对外暴露获得名称的接口
func (m *Meal) GetItems() []string {
	var items []string
	for _, item := range m.items {
		items = append(items, item.GetName())
	}
	return items
}

// 定义饭菜建造者，提供套餐
type MealBuilder struct{}

// 套餐A，汉堡+饮料
func (b *MealBuilder) CreateMealA() Meal {
	meal := Meal{}
	meal.addItem(&burger{price: 10, name: "burger"})
	meal.addItem(&drink{price: 5, name: "drink"})
	return meal
}

// 套餐B，2个汉堡+2个饮料
func (b *MealBuilder) CreateMealB() Meal {
	meal := Meal{}
	meal.addItem(&burger{price: 10, name: "burger"})
	meal.addItem(&burger{price: 10, name: "burger"})
	meal.addItem(&drink{price: 5, name: "drink"})
	meal.addItem(&drink{price: 5, name: "drink"})
	return meal
}

func main() {
	builder := MealBuilder{}
	// 要一个套餐A，查看价格和名称
	meal := builder.CreateMealA()
	fmt.Printf("Meal A: %s, cost: %.2f\n", meal.GetItems(), meal.GetCost())
	// 要一个套餐B，查看价格和名称
	meal = builder.CreateMealB()
	fmt.Printf("Meal B: %s, cost: %.2f\n", meal.GetItems(), meal.GetCost())
}
